from app.exec import exec
from SystemInfo import CpuConstants,GetMemInfo
import re
from utils.common import exec_shell
from flask import jsonify,request
from app.models import AcousticModel,LexiconDict,LanguageModel,Decoder,Model,Dataset,DataPreprocessor,FPFE,PostProcessor,BTTask,BTExecute,TestProject
from sqlalchemy import and_,or_

bCollapse=False

@exec.route('/notCollapse')
def notCollapse():
    global bCollapse
    bCollapse=False
    return 'ok'

@exec.route('/collapse')
def collapse():
    global bCollapse
    bCollapse=True
    return 'ok'

@exec.route('/b_collapse')
def b_collapse():
    global bCollapse
    return jsonify({'data':bCollapse})

@exec.route('/heartbeat',methods=['GET'])
def heartbeat():
    return jsonify({'data':'yes'})

@exec.route('/detect_devices',methods=['GET'])
def detect_devices():
    cpu_constants=CpuConstants()
    mem_dict=GetMemInfo()
    res=re.search(r'\S+Hz',cpu_constants.cpuName)
    cpu_freq=res.group()

    cpu={'name':cpu_constants.cpuName,'device_id':-1,'freq':cpu_freq,'mem_size':f"{mem_dict['memTotal']}MB"}

    devices=[]
    ns_list,_=exec_shell('nvidia-smi -L')
    if ns_list!=-1000:
        ns_list=ns_list.decode().strip().split('\n')
        for ni in range(len(ns_list)):
            query_gpu_res,_=exec_shell(f'nvidia-smi --query-gpu=name,pci.device,clocks.max.sm,memory.total -i {ni} --format=csv,noheader')
            name,device_id,max_freq,mem_size=query_gpu_res.decode().strip().split(', ')
            devices.append({'name':name,'device_id':int(device_id,16),'freq':max_freq,'mem_size':mem_size})
    devices.append(cpu)

    d={'devices':devices}
    return jsonify(d)

@exec.route('/acoustic_model',methods=['GET'])
def acoustic_model():
    page=int(request.args.get('page',default=1))
    per_page=int(request.args.get('per_page',default=10))

    acoustic_models=AcousticModel.query.order_by(AcousticModel.last_active.desc()).paginate(page=page,per_page=per_page)
    if page>2:
        page_range=range(1,acoustic_models.pages+1)[page-3:page+2]
    else:
        page_range=range(1,acoustic_models.pages+1)[:5]
    ams=[]
    for acoustic_model in acoustic_models:
        ams.append([acoustic_model.id,acoustic_model.name])
    return jsonify({'acoustic_models':ams,'page_range':list(page_range)})

@exec.route('/lexicon_dict',methods=['GET'])
def lexicon_dict():
    page=int(request.args.get('page',default=1))
    per_page=int(request.args.get('per_page',default=10))

    lexicon_dicts=LexiconDict.query.order_by(LexiconDict.last_active.desc()).paginate(page=page,per_page=per_page)
    if page>2:
        page_range=range(1,lexicon_dicts.pages+1)[page-3:page+2]
    else:
        page_range=range(1,lexicon_dicts.pages+1)[:5]
    lds=[]
    for lexicon_dict in lexicon_dicts:
        lds.append([lexicon_dict.id,lexicon_dict.name])
    return jsonify({'lexicon_dicts':lds,'page_range':list(page_range)})

@exec.route('/language_model',methods=['GET'])
def language_model():
    page=int(request.args.get('page',default=1))
    per_page=int(request.args.get('per_page',default=10))

    language_models=LanguageModel.query.order_by(LanguageModel.last_active.desc()).paginate(page=page,per_page=per_page)
    if page>2:
        page_range=range(1,language_models.pages+1)[page-3:page+2]
    else:
        page_range=range(1,language_models.pages+1)[:5]
    lms=[]
    for language_model in language_models:
        lms.append([language_model.id,language_model.name])
    return jsonify({'language_models':lms,'page_range':list(page_range)})

@exec.route('/decoder',methods=['GET'])
def decoder():
    page=int(request.args.get('page',default=1))
    per_page=int(request.args.get('per_page',default=10))

    decoders=Decoder.query.order_by(Decoder.last_active.desc()).paginate(page=page,per_page=per_page)
    if page>2:
        page_range=range(1,decoders.pages+1)[page-3:page+2]
    else:
        page_range=range(1,decoders.pages+1)[:5]
    dcdrs=[]
    for decoder in decoders:
        dcdrs.append([decoder.id,decoder.name])
    return jsonify({'decoders':dcdrs,'page_range':list(page_range)})

@exec.route('/check_model_name',methods=['GET'])
def check_model_name():
    name=request.args.get('name',default='')
    id=int(request.args.get('id',default=-1))
    filter={and_(Model.id!=id,Model.name==name)}
    if Model.query.filter(*filter).first():
        return jsonify({'res':False})
    else:
        return jsonify({'res':True})

@exec.route('/dataset',methods=['GET'])
def dataset():
    page=int(request.args.get('page',default=1))
    per_page=int(request.args.get('per_page',default=10))

    datasets=Dataset.query.order_by(Dataset.last_active.desc()).paginate(page=page,per_page=per_page)
    if page>2:
        page_range=range(1,datasets.pages+1)[page-3:page+2]
    else:
        page_range=range(1,datasets.pages+1)[:5]
    ds=[]
    for dataset in datasets:
        ds.append([dataset.id,dataset.name])
    return jsonify({'datasets':ds,'page_range':list(page_range)})

@exec.route('/fpfe',methods=['GET'])
def fpfe():
    page=int(request.args.get('page',default=1))
    per_page=int(request.args.get('per_page',default=10))

    fpfes=FPFE.query.order_by(FPFE.last_active.desc()).paginate(page=page,per_page=per_page)
    if page>2:
        page_range=range(1,fpfes.pages+1)[page-3:page+2]
    else:
        page_range=range(1,fpfes.pages+1)[:5]
    ffs=[]
    for fpfe in fpfes:
        ffs.append([fpfe.id,fpfe.name,fpfe.typ])
    return jsonify({'fpfes':ffs,'page_range':list(page_range)})

@exec.route('/fp',methods=['GET'])
def fp():
    page=int(request.args.get('page',default=1))
    per_page=int(request.args.get('per_page',default=10))

    fps=FPFE.query.filter(or_(FPFE.typ==0,FPFE.typ==2)).order_by(FPFE.last_active.desc()).paginate(page=page,per_page=per_page)
    if page>2:
        page_range=range(1,fps.pages+1)[page-3:page+2]
    else:
        page_range=range(1,fps.pages+1)[:5]
    fs=[]
    for fp in fps:
        fs.append([fp.id,fp.name,fp.typ])
    return jsonify({'fps':fs,'page_range':list(page_range)})

@exec.route('/fe',methods=['GET'])
def fe():
    page=int(request.args.get('page',default=1))
    per_page=int(request.args.get('per_page',default=10))

    fes=FPFE.query.filter_by(typ=1).order_by(FPFE.last_active.desc()).paginate(page=page,per_page=per_page)
    if page>2:
        page_range=range(1,fes.pages+1)[page-3:page+2]
    else:
        page_range=range(1,fes.pages+1)[:5]
    fs=[]
    for fe in fes:
        fs.append([fe.id,fe.name,fe.typ])
    return jsonify({'fes':fs,'page_range':list(page_range)})

@exec.route('/data_preprocessor',methods=['GET'])
def data_preprocessor():
    page=int(request.args.get('page',default=1))
    per_page=int(request.args.get('per_page',default=10))

    data_preprocessors=DataPreprocessor.query.order_by(DataPreprocessor.last_active.desc()).paginate(page=page,per_page=per_page)
    if page>2:
        page_range=range(1,data_preprocessors.pages+1)[page-3:page+2]
    else:
        page_range=range(1,data_preprocessors.pages+1)[:5]
    dps=[]
    for data_preprocessor in data_preprocessors:
        dps.append([data_preprocessor.id,data_preprocessor.name])
    return jsonify({'data_preprocessors':dps,'page_range':list(page_range)})

@exec.route('/model',methods=['GET'])
def model():
    page=int(request.args.get('page',default=1))
    per_page=int(request.args.get('per_page',default=10))

    models=Model.query.order_by(Model.last_active.desc()).paginate(page=page,per_page=per_page)
    if page>2:
        page_range=range(1,models.pages+1)[page-3:page+2]
    else:
        page_range=range(1,models.pages+1)[:5]
    ms=[]
    for model in models:
        ms.append([model.id,model.name])
    return jsonify({'models':ms,'page_range':list(page_range)})

@exec.route('/post_processor',methods=['GET'])
def post_processor():
    page=int(request.args.get('page',default=1))
    per_page=int(request.args.get('per_page',default=10))

    post_processors=PostProcessor.query.order_by(PostProcessor.last_active.desc()).paginate(page=page,per_page=per_page)
    if page>2:
        page_range=range(1,post_processors.pages+1)[page-3:page+2]
    else:
        page_range=range(1,post_processors.pages+1)[:5]
    pps=[]
    for post_processor in post_processors:
        pps.append([post_processor.id,post_processor.name])
    return jsonify({'post_processors':pps,'page_range':list(page_range)})

@exec.route('/check_bttask_name',methods=['GET'])
def check_bttask_name():
    name=request.args.get('name',default='')
    id=int(request.args.get('id',default=-1))
    filter={and_(BTTask.id!=id,BTTask.name==name)}
    if BTTask.query.filter(*filter).first():
        return jsonify({'res':False})
    else:
        return jsonify({'res':True})
    
@exec.route('/get_cur_status/<bttask_id>')
def get_cur_status(bttask_id):
    bttask=BTTask.query.filter_by(id=bttask_id).first()
    return jsonify({'res':bttask.status})

@exec.route('/check_test_project_name',methods=['GET'])
def check_test_project_name():
    name=request.args.get('name',default='')
    id=int(request.args.get('id',default=-1))
    filter={and_(TestProject.id!=id,TestProject.name==name)}
    if TestProject.query.filter(*filter).first():
        return jsonify({'res':False})
    else:
        return jsonify({'res':True})